#pragma once

#include <iostream>
#include <memory>
#include <functional>
#include "Socket.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
#include "Connection.hpp"
#include "Reactor.hpp"

using namespace LogModule;
using namespace SocketModule;

using func_t = std::function<std::string(std::string &)>;

class IOService: public Connection
{
    static const int size = 1024;
public:
    IOService(int sockfd)
    {
        SetSockfd(sockfd);
        SetEvents(EPOLLIN | EPOLLET);
    }

    // 
    virtual void Recver() override
    {
        // 1.
        while(true)
        {
            char buffer[size];
            ssize_t n = recv(Sockfd(), buffer, sizeof(buffer) - 1, 0); //非阻塞
            if(n > 0)
            {
                buffer[n] = 0;
                // 读取成功
                Append(buffer);
                LOG(LogLevel::INFO) << "收到数据: " << buffer;
                //LOG(LogLevel::INFO) << "Inbuffer: " << InBuffer();
            }
            else if (n == 0)
            {
                // 对端关闭连接
                Exceptor();
                return;
            }
            else
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if(errno == EINTR)
                {
                    continue;
                }
                else
                {
                    // 其他错误
                    Exceptor();
                    return;
                }
            }
        }
        std::string result;
        if(_on_message)
            result = _on_message(InBuffer());

        // 添加应答信息
        AppendToOut(result);

        // 如何处理写的问题，
        if (!IsOutBufferEmpty())
            Sender();
    }

    virtual void Sender() override
    {
        // 直接写
        while(true)
        {
            ssize_t n = send(Sockfd(), OutBuffer().c_str(), OutBuffer().size(), 0);
            if(n > 0)
            {
                // 成功
                DisCardOutString(n);
            }
            else if(n == 0)
            {
                break;
            }
            else
            {
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    // 缓冲区写满了，下次再来
                    break;
                }
                else if(errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Exceptor();
                    return;
                }
            }
        }

        // 
        if(!IsOutBufferEmpty())
        {
            // 修改对sockfd的时间关心！ --- 开启对写事件的关心
            // 按需设置
            GetOwner()->EnableReadWrite(Sockfd(), true, true);
        }
        else
        {
            GetOwner()->EnableReadWrite(Sockfd(), true, false);
        }
    }

    virtual void Exceptor() override
    {
        // IO读取的时候，所有的异常处理，全部都会转化成为这个一个函数的调用
        // 出现异常，我们怎么做？？？
        // 打印日志，差错处理，关闭连接，Reactor异常connection，从内核中移除对fd的关心
        LOG(LogLevel::INFO) << "客户端连接可能结束, 进行异常处理: " << Sockfd();
        GetOwner()->DelConnection(Sockfd());
    }

    void REgisterOnMessage(func_t on_message)
    {
        _on_message = on_message;
    }

    ~IOService(){}
private:
    func_t _on_message;
};